Skip to content

feat(vm): Comparable residuals + strict Time/Date parsers - #344

Merged
tannevaled merged 2 commits into
mainfrom
feat/comparable-time-parsers
Aug 10, 2026
Merged

feat(vm): Comparable residuals + strict Time/Date parsers#344
tannevaled merged 2 commits into
mainfrom
feat/comparable-time-parsers

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Horodate: 2026-08-10 08:42 CEST

Adds the strict require 'time' / require 'date' class-method parsers, and locks in the Comparable residuals (already provided by the prelude) behind an explicit MRI-4.0.5 test.

(A) Comparable residuals

clamp (2-arg + Range incl. beginless/endless; exclusive-range and reversed-bound ArgumentError, non-Range TypeError), between?, and the <=>-derived operators < <= > >= == — including the exact ArgumentError "comparison of X with Y failed" when <=> is nil, and == staying lenient. These already lived in internal/vm/prelude.rb; this PR verifies them against ruby 4.0.5 (including that == propagates a raising <=> exactly as MRI does) rather than re-implementing.

(B) strict Time / Date / DateTime parsers

internal/vm/strict_parsers.go — each accepts only its wire format (a fixed set of Go reference layouts tried in order) and raises MRI's exact error otherwise:

method(s) grammar malformed error
Time.iso8601 / .xmlschema YYYY-MM-DDTHH:MM:SS(.fff)?(Z|±HH:MM)? ArgumentError "invalid xmlschema format: <str>"
Time.rfc2822 / .rfc822 Wdy, DD Mon YYYY HH:MM:SS ±HHMM ArgumentError "not RFC 2822 compliant date: <str>"
Time.httpdate RFC 1123 + obsolete RFC 850 + asctime ArgumentError "not RFC 2616 compliant date: <str>"
Date/DateTime .iso8601 .xmlschema .rfc3339 .rfc2822 .rfc822 .httpdate as above (Date drops the time; DateTime keeps wall clock + offset) Date::Error "invalid date"

Date / DateTime rebuild through the go-ruby-date constructors, so the reform, JDN core and formatters stay authoritative; round-trips through the instance formatters (#iso8601/#rfc2822/#httpdate/…) hold.

Deferred

  • Date.jisx0301 / DateTime.jisx0301 — the Japanese-era table (M/T/S/H/R base years) is unexported in go-ruby-date; a follow-up should expose or mirror it.
  • A zone-less Time.iso8601 resolves to UTC here (deterministic) where MRI uses the machine local zone — the one inherently non-deterministic case.

Verification

  • go test ./... green; whole-package coverage gate shows only the 10 pre-existing tolerated partials — every new function is 100% incl. error branches.
  • gofmt + go vet ./internal/vm/ clean.
  • ruby/spec ratchet: 12382 passing (files loaded 2103) — FLOOR 12351 → 12352.

🤖 Generated with Claude Code

tannevaled and others added 2 commits August 10, 2026 08:33
Horodate: 2026-08-10 08:22 CEST

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Horodate: 2026-08-10 08:41 CEST

Adds the strict "require 'time'" / "require 'date'" class-method parsers and
locks in the Comparable residuals (clamp / between? / <=>-derived operators),
which the prelude already provided, behind an explicit MRI-4.0.5 test.

WHAT
- internal/vm/strict_parsers.go: Time.iso8601/.xmlschema/.rfc2822/.rfc822/
  .httpdate and the Date / DateTime siblings iso8601/xmlschema/rfc3339/rfc2822/
  rfc822/httpdate. Each accepts ONLY its wire format (a fixed set of Go
  reference layouts, tried in order) and raises MRI's exact error otherwise:
  ArgumentError "invalid xmlschema format: <str>" / "not RFC 2822 compliant
  date: <str>" / "not RFC 2616 compliant date: <str>" for Time, Date::Error
  "invalid date" for Date / DateTime. httpdate accepts the three RFC 2616 forms
  (RFC 1123, obsolete RFC 850, asctime). Date / DateTime rebuild through the
  go-ruby-date constructors, so the reform, JDN core and formatters stay
  authoritative; round-trips through the instance formatters hold.
- Wired via registerStrictTimeParsers (registerTime) and
  registerStrictDateParsers (registerDate).
- internal/vm/strict_parsers_test.go: happy paths, several malformed ->
  ArgumentError / Date::Error cases, formatter round-trips, and the Comparable
  clamp / between? / nil-<=> operator errors — all asserted against ruby 4.0.5.

DEFERRED
- Date.jisx0301 / DateTime.jisx0301: the Japanese-era table (M/T/S/H/R base
  years) is unexported in go-ruby-date; a follow-up should expose or mirror it.
- A zone-less Time.iso8601 resolves to UTC here (deterministic) where MRI uses
  the machine local zone — the one inherently non-deterministic case.

VERIFICATION
- go test ./... green (whole-package coverage gate shows only the 10 pre-existing
  tolerated partials; every new function is 100% incl error branches).
- gofmt + go vet ./internal/vm/ clean.
- ruby/spec ratchet: 12382 passing (files loaded 2103); FLOOR 12351 -> 12352.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit f834e6f into main Aug 10, 2026
5 of 7 checks passed
@tannevaled
tannevaled deleted the feat/comparable-time-parsers branch August 10, 2026 07:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant